/*
package com.css.gateway.filter;

*/
/*import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSON;
import com.invoice.tcc.cons.Result;
import com.invoice.tcc.cons.SsoConstants;
import com.invoice.tcc.session.SessionManager;
import com.invoice.tcc.session.SessionUtils;
import com.invoice.tcc.util.*;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;*//*


import com.alibaba.fastjson.JSON;
import com.css.common.core.constant.Result;
import com.css.common.core.constant.SsoConstants;
import com.css.common.core.session.Session;
import com.css.common.core.session.ReactiveSessionManager;
import com.css.common.core.utils.SecurityUtils;
import com.css.common.core.utils.ServletUtils;
import com.css.common.core.utils.StringUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.data.redis.core.ReactiveRedisTemplate;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseCookie;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
import org.springframework.http.HttpCookie;
import com.alibaba.fastjson.TypeReference;

import java.time.Duration;
import java.time.temporal.ChronoUnit;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import static com.css.common.core.constant.SsoConstants.COOKIE_TOKEN_KEY;


@Slf4j
@Component
public class ReactiveSecurityFilter implements GlobalFilter {

    @Autowired
    private ReactiveRedisTemplate<String, String> redisTemplate;

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        ServerHttpRequest request = exchange.getRequest();
        String url = request.getURI().getPath();
        // 跳过不需要验证的路径
        if (StringUtils.matches(url, SecurityUtils.WHITELIST))//白名单
        {
            log.info("url设置了白名单");
            return chain.filter(exchange);
        }
        log.info("url未设置白名单");

        return getTokenFromRequest(exchange.getRequest())
                .flatMap(token -> loadSessionFromRedis(token, exchange)
                        .flatMap(session -> {
                            // 将会话存入上下文后继续执行过滤器链
                            return chain.filter(exchange)
                                    .contextWrite(ctx -> ctx.put(ReactiveSessionManager.SESSION_CONTEXT_KEY, session));
                        })
                )
                .onErrorResume(e -> handleAuthError(exchange.getResponse(), e));
    }

    private Mono<String> getTokenFromRequest(ServerHttpRequest request) {
        return Mono.justOrEmpty(request.getCookies().getFirst(LOGIN_USER_HEADER))
                .map(HttpCookie::getValue)
                .switchIfEmpty(Mono.justOrEmpty(
                        request.getHeaders().getFirst(LOGIN_USER_HEADER)
                ));
    }

    private Mono<Session> loadSessionFromRedis(String token, ServerWebExchange exchange) {
        return redisTemplate.opsForHash().get(token, "yhxx")
                .switchIfEmpty(Mono.error(new SecurityException("没有登录！")))
                .flatMap(data -> {
                    // 1. 解析Redis数据到Session对象
                    Session session = new Session();
                    try {
                        Map<String, Object> userInfo = JSON.parseObject(
                                data.toString(),  // 确保data是String类型
                                new TypeReference<Map<String, Object>>() {}
                        );
                        userInfo.forEach(session::setAttribute);
                    } catch (Exception e) {
                        return Mono.error(new SecurityException("会话解析失败"));
                    }

                    // 2. 处理Cookie并返回会话
                    return handleSessionCookie(exchange.getResponse(), token)
                            .then(Mono.just(session)); // 使用创建的session对象
                });
    }


    private Mono<Void> handleAuthError(ServerHttpResponse response, Throwable e) {
        response.setStatusCode(HttpStatus.UNAUTHORIZED);
        return response.writeWith(Mono.just(response.bufferFactory()
                .wrap(Result.error(401, e.getMessage()).toString().getBytes())));
    }


    private Mono<Void> handleSessionCookie(ServerHttpResponse response, String token) {
        // 创建响应式 Cookie
        ResponseCookie cookie = ResponseCookie.from(LOGIN_USER_HEADER, token)
                .path(SsoConstants.COOKIE_PATH)
                .httpOnly(true)
                .maxAge(TimeUnit.DAYS.toSeconds(7)) // 设置7天有效期
                .build();

        // 添加 Cookie 到响应头
        response.addCookie(cookie);

        // 设置 Redis 过期时间（响应式操作）
        return redisTemplate.expire(token, Duration.of(7, ChronoUnit.DAYS))
                .then(Mono.empty()); // 转换为 Mono<Void>
    }


    private void addHeader(ServerHttpRequest.Builder mutate, String name, Object value)
    {
        if (value == null)
        {
            return;
        }
        String valueStr = value.toString();
        String valueEncode = ServletUtils.urlEncode(valueStr);
        mutate.header(name, valueEncode);
    }

    private void removeHeader(ServerHttpRequest.Builder mutate, String name)
    {
        mutate.headers(httpHeaders -> httpHeaders.remove(name)).build();
    }

    private Mono<Void> unauthorizedResponse(ServerWebExchange exchange, String msg)
    {
        log.error("[鉴权异常处理]请求路径:{}", exchange.getRequest().getPath());
        return ServletUtils.webFluxResponseWriter(exchange.getResponse(), msg, HttpStatus.UNAUTHORIZED.value());
    }






    private static final String LOGIN_USER_HEADER = "ACCESSTOKEN";

   */
/* @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
            throws IOException, ServletException {       
        final List<String> whiteList = SecurityUtils.WHITELIST;//白名单
        //log.info("url白名单配置：{}",whiteList+"");
        String servletPath = request.getRequestURI();
        log.info("url:{}",servletPath);
        if ((!GyUtils.isNull(whiteList) && (whiteList.contains(servletPath)) || servletPath.contains("api/"))){
            log.info("url设置了白名单");
        	request = new AuthRequestWrapper(request);
            filterChain.doFilter(request, response);
        }else {
            log.info("url未设置白名单");
//            final String token = request.getHeader(LOGIN_USER_HEADER);
            String token = "";
            Cookie[] cookies = request.getCookies();
            if (GyUtils.isNull(cookies)){
                token = request.getHeader(LOGIN_USER_HEADER);
            }else {
                List<Cookie> collect = Arrays.stream(cookies).filter(v -> v.getName().equals(LOGIN_USER_HEADER)).collect(Collectors.toList());
                if (!GyUtils.isNull(collect)){
                    token = collect.get(0).getValue();
                }
            }
            if (null != token){
                Map yhxx = JSONUtil.toBean(RedisUtils.getHash(token,"yhxx"), Map.class);
                if (GyUtils.isNull(yhxx)){
                    // 返回登录提示信息-401
                    ResponseUtil.out(response,Result.error(401,"无效的会话，或者会话已过期，请重新登录！"));
                    throw new ServletException("无效的会话，或者会话已过期，请重新登录！");
                }else {
                    final Cookie cookie = new Cookie(LOGIN_USER_HEADER,token);
                    cookie.setPath(SsoConstants.COOKIE_PATH);
                    cookie.setHttpOnly(true);
                    response.addCookie(cookie);
                    RedisUtils.expire(token,7, TimeUnit.DAYS);
                }

                SessionManager.get().setGlzhbz("31".equals(yhxx.get("yhdlsfdm")) ? "Y" : "N");//管理员账号标志：Y是管理
                SessionManager.get().setYhdlzh(BaseUtil.object2Str(yhxx.get("yhdlzh")));//用户登录账号
                SessionManager.get().setQysh(BaseUtil.object2Str(yhxx.get("qysh")));//企业税号
                SessionManager.get().setQymc(BaseUtil.object2Str(yhxx.get("qymc")));//企业税号
                SessionManager.get().setYhdlsfdm(BaseUtil.object2Str(yhxx.get("yhdlsfdm")));//用户登录身份代码
                SessionManager.get().setQyid(BaseUtil.object2Str(yhxx.get("qyid")));//企业id
                SessionManager.get().setZrrid(BaseUtil.object2Str(yhxx.get("zrrid")));//自然人id
                SessionManager.get().setZrrxm(BaseUtil.object2Str(yhxx.get("xm")));//自然人姓名
                SessionManager.get().setZrrzjhm(BaseUtil.object2Str(yhxx.get("sfzjhm")));//自然人证件号码
                SessionManager.get().setZrrsjhm(BaseUtil.object2Str(yhxx.get("sjh")));//自然人手机号码
                try {
                    SessionManager.get().setXtqdDm(!BaseUtil.isNull(yhxx.get("xtqdDm"))?Integer.valueOf(yhxx.get("xtqdDm")+""):null);//渠道代码
                }catch (Exception e){
                    log.info("获取xtqdDm异常："+e);
                }
                SessionManager.get().setMap(yhxx);
                log.info("session:yhmm:{}", JSON.toJSONString(yhxx));
                log.info("session:zrrid:{}", SessionUtils.getZrrid());
                filterChain.doFilter(request, response);
            }else{
                // 返回登录提示信息-401
                ResponseUtil.out(response,Result.error(401,"未登录，请先登录后再访问"));
                throw new ServletException("未登录，请先登录后再访问！");
            }
        }
    }

    @Override
    public void destroy() {
        SessionManager.get().clear();
    }*//*


}
*/
